package com.ts.api.module.channel.service.impl;

import com.gitee.apanlh.util.base.Eq;
import com.gitee.apanlh.util.valid.ValidParam;
import com.ts.api.common.constant.channel.ChannelIsRegisterEnum;
import com.ts.api.module.channel.dao.ChannelFormDao;
import com.ts.api.module.channel.dao.ChannelHistoryFormDao;
import com.ts.api.module.channel.dao.ChannelHistoryUserDao;
import com.ts.api.module.channel.dao.ChannelUserDao;
import com.ts.api.module.channel.entity.po.ChannelUserFormPO;
import com.ts.api.module.channel.entity.po.ChannelUserRegisterPO;
import com.ts.api.module.channel.entity.qo.ChannelUserQO;
import com.ts.api.module.channel.service.DoubleWriteUserService;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
public class DoubleWriteUserServiceImpl implements DoubleWriteUserService {

    @Autowired
    private ChannelHistoryUserDao channelHistoryUserDao;
    @Autowired
    private ChannelUserDao channelUserDao;
    @Autowired
    private ChannelHistoryFormDao channelHistoryFormDao;
    @Autowired
    private ChannelFormDao channelFormDao;
    @Autowired
    private RedissonClient redissonClient;

    @Override
    public ChannelUserRegisterPO insertUser(ChannelUserRegisterPO channelUserRegisterPO) {
        String phoneMd5 = channelUserRegisterPO.getPhoneMd5();

        RLock lock = redissonClient.getLock("insert_user:" + phoneMd5);
        lock.lock(10, TimeUnit.SECONDS);
        try {
            ChannelUserQO channelUserQO = ChannelUserQO.createPhoneMd5(phoneMd5);
            //  获取老库
            ChannelUserRegisterPO historyUserRegisterPO = channelHistoryUserDao.get(channelUserQO);
            //  获取当前库
            ChannelUserRegisterPO currentUserRegisterPO = channelUserDao.get(channelUserQO);

            //  新老库同时存在则抛出异常
            if (ValidParam.isNotNull(historyUserRegisterPO, currentUserRegisterPO)) {
                throw new DuplicateKeyException("用户抢先注册-用户已重复");
            }

            //  当老库不存在则新增(channelUserRegisterPO生成id)
            if (ValidParam.isNull(historyUserRegisterPO)) {
                channelHistoryUserDao.insert(channelUserRegisterPO);
            } else {
                channelUserRegisterPO.setId(historyUserRegisterPO.getId());

                //  需要存在新的用户名，才进行更新历史库已最新的为准（联登无用户姓名）
                if (ValidParam.isNotNull(channelUserRegisterPO.getUserName())) {
                    channelUserRegisterPO.setIsChannelRegister(ChannelIsRegisterEnum.OLD.getType());
                    channelHistoryUserDao.update(channelUserRegisterPO);
                }
            }

            //  当前库不存在则插入
            if (ValidParam.isNull(currentUserRegisterPO)) {
                //  如果历史库存在-当前库插入用户也是老用户
                if (ValidParam.isNotNull(historyUserRegisterPO)) {
                    channelUserRegisterPO.setIsChannelRegister(ChannelIsRegisterEnum.OLD.getType());
                } else {
                    channelUserRegisterPO.setIsChannelRegister(ChannelIsRegisterEnum.NEW.getType());
                }
                channelUserDao.insert(channelUserRegisterPO);
            } else {
                //  如果是新用户则更新成老用户
                if (Eq.object(ChannelIsRegisterEnum.NEW.getType(), channelUserRegisterPO.getIsChannelRegister())) {
                    channelUserRegisterPO.setIsChannelRegister(ChannelIsRegisterEnum.OLD.getType());
                    channelUserRegisterPO.setId(currentUserRegisterPO.getId());
                    channelUserDao.update(channelUserRegisterPO);
                }
            }
        } finally {
            lock.unlock();
        }
        return channelUserRegisterPO;
    }

    @Transactional(rollbackFor = Exception.class)
    public void updateUser(ChannelUserRegisterPO userRegisterPO) {
        channelHistoryUserDao.update(userRegisterPO);
        channelUserDao.update(userRegisterPO);
    }

    @Override
    public void batchInsertUserForm(List<ChannelUserFormPO> listChannelUserFormPO) {
        channelHistoryFormDao.batchInsertUserForm(listChannelUserFormPO);
        channelFormDao.batchInsertUserForm(listChannelUserFormPO);
    }

    @Override
    public void removeByUserId(Long userId) {
        channelHistoryFormDao.removeByUserId(userId);
        channelFormDao.removeByUserId(userId);
    }
}
